﻿using System;
using System.IO;
using Core.Extension;
using UnityEngine;
using UnityEngine.Serialization;

namespace Logic.Global
{
    public class CaptureTool : SingletonMono<CaptureTool>
    {
        [HideInInspector] public Camera camera;
        private RenderTexture _renderTexture;
        private Action<Texture2D> _callback;
        private bool _captureStillImage = false;

        protected void Awake()
        {
            gameObject.SetActive(false);
            camera = GetComponent<Camera>();
        }

        public void Capture(int photoWidth, int photoHigh, Action<Texture2D> cb, bool isDrawLogo = false)
        {
            _renderTexture = RenderTexture.GetTemporary(photoWidth, photoHigh, 24);
            _renderTexture.name = "RenderTex MakeBy Capture()";
            _callback = cb;
            gameObject.SetActive(true);
            _captureStillImage = true;
            camera.targetTexture = _renderTexture;
            camera.Render();
            camera.targetTexture = null;
        }

        /// <summary>
        /// 耗费性能，勿频繁调用。1S内最多2次
        /// </summary>
        /// <param name="spriteRenderer"></param>
        /// <param name="cb"></param>
        /// <param name="isUseSrSize">是否直接使用SpriteRenderer的尺寸，而非Sprite的分辨率</param>
        /// <param name="sizeScale">相片尺寸缩小几倍</param>
        public void Capture(SpriteRenderer spriteRenderer, Action<Texture2D> cb, bool isUseSrSize = false,
            int sizeScale = 1)
        {
            camera.transform.position = GameCamera.Ins.transform.position;
            camera.orthographicSize = GameCamera.Ins.gameCamera.orthographicSize;
            Vector3 srPos = spriteRenderer.transform.position;
            transform.position = new Vector3(srPos.x, srPos.y, transform.position.z);
            if (isUseSrSize)
            {
                Vector2 srSize = spriteRenderer.size;
                camera.orthographicSize = srSize.y / 2f;
                Capture((int) (srSize.x * 100 / sizeScale), (int) (srSize.y * 100 / sizeScale), cb);
            }
            else
            {
                Rect rect = spriteRenderer.sprite.rect;
                camera.orthographicSize = rect.height / 200f;
                Capture((int) rect.width / sizeScale, (int) rect.height / sizeScale, cb);
            }
        }

        void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
        {
            if (_captureStillImage)
            {
                Graphics.Blit(sourceTexture, destTexture);
                Texture2D t = GetRTPixels(destTexture);
                RenderTexture.ReleaseTemporary(_renderTexture);
                _captureStillImage = false;
                gameObject.SetActive(false);
                _callback?.Invoke(t);
                t.Apply();
            }
            else
            {
                Graphics.Blit(sourceTexture, destTexture);
            }
        }

        private Texture2D GetRTPixels(RenderTexture rt)
        {
            RenderTexture currentActiveRT = RenderTexture.active;
            RenderTexture.active = rt;
            GL.PushMatrix();
            GL.LoadPixelMatrix(0, rt.width, rt.height, 0);
            Texture2D outTexture = new Texture2D(_renderTexture.width, _renderTexture.height,
                TextureFormat.RGBA32, false);
            outTexture.name = "Texture2D Make By GetRTPixels()";
            outTexture.ReadPixels(new Rect(0, 0, _renderTexture.width, _renderTexture.height),
                0, 0);
            outTexture.Apply();
            RenderTexture.ReleaseTemporary(_renderTexture);
            RenderTexture.active = currentActiveRT;
            GL.PopMatrix(); //
            return outTexture;
        }
    }
}